
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "hashtool.h"

vhash* hash_new(int size) {
	size = (size <= 0) ? 8 : size;
	vhash *h = (vhash*)alloc(sizeof(vhash));
	h->ncells = size;
	h->nitems = 0;

	h->cells = (hcell**)malloc(sizeof(hcell*) * size);
	for(int i=0; i<size; i++)
		h->cells[i] = NULL;
	return h;
}

value hash_to_value(vhash *h) {
	return alloc_abstract(k_hash,h);
}

int hash_set(vhash *h, value key, value val) {
	hcell *cell;
	int hkey = val_hash(key);
	cell = h->cells[hkey % h->ncells];

	while(cell) {
		if( !val_compare(key, cell->key) ) {
			cell->val = val;
			return 0;
		}
		cell = cell->next;
	}

	if( h->nitems >= h->ncells )
		hash_resize(h, h->ncells << 1);

	cell = (hcell *) malloc(sizeof(hcell));
	cell->hkey = hkey;
	cell->key = key;
	cell->val = val;
	hkey %= h->ncells;
	cell->next = h->cells[hkey];
	h->cells[hkey] = cell;
	h->nitems++;
	return 1;
}

static void add_rec( hcell **cc, int size, hcell *c ) {
	int k;
	if(!c) return;
	add_rec(cc, size, c->next);
	k = c->hkey % size;
	c->next = cc[k];
	cc[k] = c;
}

void hash_resize(vhash *h, int size ) {
	if(size <= 0) size = 8;
	if(size <= h->ncells) return;
	hcell **cc = (hcell**)malloc(sizeof(hcell*)*size);
	memset(cc, 0, sizeof(hcell*)*size);
	for(int i=0; i<h->ncells; i++)
		add_rec(cc, size, h->cells[i]);
	h->cells = cc;
	h->ncells = size;
}



